﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using System.Net;

namespace Web.HttpUtility
{
    public class HttpOptions
    {
        public HttpOptions()
        {
            Method = "GET";
            Accept = "image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*";
            UserAgent = "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 2.0.50727; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022)";
            ContentType = "utf-8";
        }

        public static HttpOptions CreatePostOptions()
        {
            return new HttpOptions
            {
                ContentType = "application/x-www-form-urlencoded; charset=UTF-8"
            };
        }
        public string Url { get; set; }
        public IWebProxy Proxy { get; set; }
        public string Referer { get; set; }
        public string Accept { get; set; }
        public string UserAgent { get; set; }
        public string ContentType { get; set; }
        public string Method { get; set; }
        public string Data { get; set; }
        public CookieContainer CookieContainer { get; set; }

        public string AcceptLanguage { get; set; }

        public string AcceptEncoding { get; set; }
    }
    public static class HttpHelper
    {
        public static int ConnectionLimit = 100;

        public static string GetHtml(string url)
        {
            return GetHtml(url, "GET", null, null, null);
        }

        /// <summary>
        /// GET请求，不需要cookie
        /// </summary>
        /// <param name="url"></param>
        /// <returns></returns>
        public static string GetHtml(string url, IWebProxy proxy)
        {
            return GetHtml(url, "GET", null, null, proxy);
        }

        public static string GetHtml(string url, CookieContainer cookieContainer)
        {
            return GetHtml(url, "GET", null, cookieContainer, null);
        }

        /// <summary>
        /// GET请求，需要Cookie
        /// </summary>
        /// <param name="url"></param>
        /// <param name="cookieContainer"></param>
        /// <returns></returns>
        public static string GetHtml(string url, CookieContainer cookieContainer, IWebProxy proxy)
        {
            return GetHtml(url, "GET", null, cookieContainer, proxy);
        }

        public static string GetHtml(string url,string data,CookieContainer cookieContainer)
        {
            return GetHtml(url, "GET", data, cookieContainer, null);
        }

        /// <summary>
        /// GET请求，需要Cookie
        /// </summary>
        /// <param name="url"></param>
        /// <param name="data"></param>
        /// <param name="cookieContainer"></param>
        /// <returns></returns>
        public static string GetHtml(string url, string data, CookieContainer cookieContainer,IWebProxy proxy)
        {
            return GetHtml(url, "GET", data, cookieContainer,proxy);
        }

        /// <summary>
        /// GET或Post请求,需要Cookie
        /// </summary>
        /// <param name="url"></param>
        /// <param name="method"></param>
        /// <param name="data"></param>
        /// <param name="cookieContainer"></param>
        /// <returns></returns>
        public static string GetHtml(string url, string method, string data, CookieContainer cookieContainer)
        {
            return GetHtml(url, method, data, cookieContainer, null);
        }

        /// <summary>
        /// GET或Post请求,需要Cookie
        /// </summary>
        /// <param name="url"></param>
        /// <param name="method"></param>
        /// <param name="data"></param>
        /// <param name="cookieContainer"></param>
        /// <returns></returns>
        public static string GetHtml(string url, string method, string data, CookieContainer cookieContainer,IWebProxy proxy)
        {
            var options = method.ToUpper() == "POST" ? HttpOptions.CreatePostOptions() : new HttpOptions();
            options.Method = method.ToUpper() == "POST" ? "POST" : "GET";
            options.Url = url;
            options.Data = data;
            options.CookieContainer = cookieContainer;
            options.Proxy = proxy;
            return GetHtml(options);
        }

 
        public static string GetHtml(HttpOptions options)
        {
            string url = options.Url;
            string method = (options.Method ?? "GET").ToUpper();
            if (method != "POST")
            {
                method = "GET";
                if (!string.IsNullOrEmpty(options.Data))
                {
                    url = url.IndexOf("?") != -1 ? "&" : "?" + options.Data;
                }
            }
            var request = (HttpWebRequest)WebRequest.Create(url);
            request.Proxy = options.Proxy;
            request.Referer = options.Referer ?? url;
            request.Accept = options.Accept;
            request.UserAgent = options.UserAgent;
            request.ContentType = options.ContentType;
            request.CookieContainer = options.CookieContainer;
            request.Method = method;
            request.AllowAutoRedirect = false;
            request.KeepAlive = true;
            request.Credentials = CredentialCache.DefaultCredentials;
            request.AutomaticDecompression = DecompressionMethods.GZip| DecompressionMethods.Deflate;
            if(!string.IsNullOrEmpty(options.AcceptLanguage))
            {
                request.Headers["Accept-Language"] = options.AcceptLanguage;
            }
            if(!string.IsNullOrEmpty(options.AcceptEncoding))
            {
                request.Headers["Accept-Encoding"] = options.AcceptEncoding;
            }
            request.ServicePoint.ConnectionLimit = ConnectionLimit;
            if (method == "POST")
            {
                string data = string.IsNullOrEmpty(options.Data) ? "" : options.Data;
                byte[] buffer = Encoding.UTF8.GetBytes(data);
                request.ContentLength = buffer.Length;
                using (var stream = request.GetRequestStream())
                {
                    stream.Write(buffer, 0, buffer.Length);
                }
            }

            var response = (HttpWebResponse)request.GetResponse();
            var s = response.Headers["Set-Cookie"];
            using (var stream = response.GetResponseStream())
            {
                if (options.CookieContainer != null)
                {
                    options.CookieContainer.Add(response.Cookies);
                    //
                }
                Encoding gbk =System.Text.Encoding.GetEncoding("GBK");
                using (var reader = new StreamReader(stream,gbk))
                {
                    return reader.ReadToEnd();
                }
            }
        }
        /// <summary>
        /// GET或Post请求,需要Cookie，更多配置选项
        /// </summary>
        /// <param name="options"></param>
        /// <returns></returns>
        public static Stream GetStream(HttpOptions options)
        {
            string url = options.Url;
            string method = (options.Method ?? "GET").ToUpper();
            if (method != "POST")
            {
                method = "GET";
                if (!string.IsNullOrEmpty(options.Data))
                {
                    url = url.IndexOf("?") != -1 ? "&" : "?" + options.Data;
                }
            }
            var request = (HttpWebRequest)WebRequest.Create(url);
            request.Proxy = options.Proxy;
            //request.Referer = options.Referer;
            request.Referer = url;
            request.Accept = options.Accept;
            request.UserAgent = options.UserAgent;
            request.ContentType = options.ContentType;
            request.CookieContainer = options.CookieContainer;
            request.Method = method;
            request.ServicePoint.ConnectionLimit = ConnectionLimit;
            if (method == "POST")
            {
                string data = string.IsNullOrEmpty(options.Data) ? "" : options.Data;
                byte[] buffer = Encoding.UTF8.GetBytes(data);
                request.ContentLength = buffer.Length;
                using (var stream = request.GetRequestStream())
                {
                    stream.Write(buffer, 0, buffer.Length);
                }
            }

            var response = (HttpWebResponse)request.GetResponse();
            var output = response.GetResponseStream();
            if (options.CookieContainer != null)
            {
                options.CookieContainer.Add(response.Cookies);
            }
            return output;
        }

        public static Stream GetStream(string url, CookieContainer cookieContainer,IWebProxy proxy)
        {
            var options = new HttpOptions { Url = url, CookieContainer = cookieContainer ,Proxy=proxy};
            
            return GetStream(options);
        }

        public static Stream GetStream(string url, CookieContainer cookieContainer)
        {
            return GetStream(url, cookieContainer, null);
        }

        public static Stream GetStream(string url,IWebProxy proxy)
        {
            return GetStream(url, null, null);
        }

        public static Stream GetStream(string url)
        {
            return GetStream(url, null, null);
        }
    }
}
